LÀr dig organisera dina Django REST Framework API:er effektivt med ViewSets. Denna guide tÀcker allt frÄn grundlÀggande anvÀndning till avancerad anpassning.
Django REST Framework ViewSets: BemÀstra organisationen av API-slutpunkter
Inom modern webbutveckling Àr det avgörande att bygga robusta och vÀlorganiserade API:er. Django REST Framework (DRF) Àr en kraftfull verktygslÄda för att skapa RESTful API:er med Django. Medan DRF erbjuder olika verktyg för att skapa API-slutpunkter, ger ViewSets ett elegant sÀtt att organisera relaterade vyer i en enda klass, vilket leder till renare och mer underhÄllbar kod. Denna omfattande guide kommer att utforska ViewSets i detalj, inklusive deras fördelar, anvÀndning och avancerade anpassningstekniker.
Vad Àr ViewSets?
En ViewSet Àr en klassbaserad vy som tillhandahÄller implementationer för standardoperationer, sÄsom list
, create
, retrieve
, update
och destroy
. IstÀllet för att definiera separata vyer för varje operation, kombinerar en ViewSet dem i en enda klass, vilket förenklar API-strukturen och minskar kodredundans. ViewSets Àr sÀrskilt anvÀndbara vid arbete med modellbaserade API:er, dÀr dessa standardoperationer ofta krÀvs. TÀnk pÄ en ViewSet som en logisk gruppering av operationer pÄ en specifik resurs.
Fördelar med att anvÀnda ViewSets
- KodÄteranvÀndning: ViewSets frÀmjar kodÄteranvÀndning genom att kapsla in vanlig API-logik i en enda klass. Detta minskar redundans och gör koden lÀttare att underhÄlla.
- Förenklad routing: ViewSets förenklar routing genom att gruppera relaterade vyer under en enda URL-prefix. Detta resulterar i en renare och mer organiserad URL-struktur.
- Mindre "boilerplate"-kod: ViewSets minskar "boilerplate"-kod genom att tillhandahÄlla standardimplementationer för vanliga API-operationer. Detta gör att utvecklare kan fokusera pÄ att implementera anpassad logik specifik för deras applikation.
- FörbÀttrad lÀsbarhet: ViewSets förbÀttrar kodens lÀsbarhet genom att organisera relaterade vyer i en enda klass. Detta gör API-strukturen lÀttare att förstÄ och navigera.
- Konsistens: ViewSets hjÀlper till att sÀkerstÀlla konsistens över API:et genom att upprÀtthÄlla en standarduppsÀttning operationer och konventioner. Detta gör API:et mer förutsÀgbart och lÀttare att anvÀnda.
GrundlÀggande anvÀndning av ViewSets
LÄt oss börja med ett enkelt exempel pÄ hur man anvÀnder ViewSets för att skapa ett API för att hantera produkter. Definiera först en modell:
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
Skapa sedan en serializer för Product
-modellen:
# serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
Skapa nu en ViewSet för Product
-modellen:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
Konfigurera slutligen URL-routningen:
# urls.py
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'products', views.ProductViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Denna konfiguration kommer automatiskt att generera följande API-slutpunkter:
/products/
(GET: lista, POST: skapa)/products/{id}/
(GET: hÀmta, PUT: uppdatera, PATCH: partiell_uppdatering, DELETE: ta bort)
ModelViewSet
tillhandahÄller standardimplementationer för alla standard-CRUD-operationer. Attributet queryset
anger den uppsÀttning objekt som ViewSet ska arbeta med, och attributet serializer_class
anger den serializer som ska anvÀndas för serialisering och deserialisering av data.
Typer av ViewSets
DRF tillhandahÄller flera inbyggda ViewSet-klasser som passar olika anvÀndningsfall:
ViewSet
: Bas-klassen för alla ViewSets. Den tillhandahÄller den grundlÀggande infrastrukturen för att hantera förfrÄgningar och svar.ReadOnlyModelViewSet
: En ViewSet som tillhandahÄller skrivskyddade operationer (list
ochretrieve
). Detta Àr anvÀndbart för API:er som endast tillÄter datainhÀmtning.ModelViewSet
: En ViewSet som tillhandahÄller alla standard-CRUD-operationer (list
,create
,retrieve
,update
ochdestroy
). Detta Àr den mest anvÀnda ViewSet för modellbaserade API:er.GenericViewSet
: En ViewSet som tillhandahÄller en generell implementation för vanliga API-operationer. Detta kan anvÀndas som bas-klass för att skapa anpassade ViewSets.
Valet av rÀtt ViewSet beror pÄ de specifika kraven för ditt API. Om du bara behöver skrivskyddade operationer, anvÀnd ReadOnlyModelViewSet
. Om du behöver alla standard-CRUD-operationer, anvÀnd ModelViewSet
. Om du behöver mer kontroll över API:ets beteende kan du skapa en anpassad ViewSet genom att Àrva frÄn GenericViewSet
eller ViewSet
.
Anpassning av ViewSets
Medan de inbyggda ViewSets ger ett bekvÀmt sÀtt att skapa API:er, kan du behöva anpassa deras beteende för att uppfylla specifika krav. DRF tillhandahÄller flera sÀtt att anpassa ViewSets, inklusive att ÄsidosÀtta metoder, lÀgga till anpassade ÄtgÀrder och anvÀnda anpassade serializers.
à sidosÀttning av metoder
Du kan ÄsidosÀtta standardimplementationerna av standard-API-operationer genom att definiera metoder med samma namn i din ViewSet-klass. Du kan till exempel ÄsidosÀtta create
-metoden för att lÀgga till anpassad logik före eller efter skapandet av ett nytt objekt:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.response import Response
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
# LÀgg till anpassad logik hÀr innan objektet skapas
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
I det hÀr exemplet ÄsidosÀtter create
-metoden standardimplementationen och lÀgger till anpassad logik innan objektet skapas. Metoden perform_create
anropas för att faktiskt skapa objektet, och svaret returneras med statuskod 201 Created
.
LÀgga till anpassade ÄtgÀrder
Du kan lÀgga till anpassade ÄtgÀrder i din ViewSet med hjÀlp av dekoratören @action
. Anpassade ÄtgÀrder gör att du kan definiera nya API-slutpunkter som utför specifika operationer pÄ de resurser som hanteras av ViewSet. Du kan till exempel lÀgga till en ÄtgÀrd för att markera en produkt som "featured":
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
@action(detail=True, methods=['post'])
def feature(self, request, pk=None):
product = self.get_object()
product.is_featured = True
product.save()
serializer = self.get_serializer(product)
return Response(serializer.data)
I det hÀr exemplet definierar dekoratören @action
en ny API-slutpunkt /products/{id}/feature/
som markerar en produkt som "featured". Argumentet detail=True
anger att ÄtgÀrden opererar pÄ en specifik instans av modellen. Argumentet methods=['post']
anger att ÄtgÀrden endast accepterar POST-förfrÄgningar.
AnvÀnda anpassade serializers
Du kan anvÀnda anpassade serializers för att anpassa hur data serialiseras och deserialiseras av ViewSet. Detta Àr anvÀndbart nÀr du behöver hantera komplexa datastrukturer eller utföra anpassad validering. Du kan till exempel anvÀnda en anpassad serializer för att inkludera relaterad data i API-svaret:
# serializers.py
from rest_framework import serializers
from .models import Product, Category
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id', 'name']
class ProductSerializer(serializers.ModelSerializer):
category = CategorySerializer(read_only=True)
class Meta:
model = Product
fields = '__all__'
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
I det hÀr exemplet inkluderar ProductSerializer
en CategorySerializer
för att serialisera den relaterade kategoridatan. Detta gör att du kan hÀmta kategorinformationen tillsammans med produktinformationen i en enda API-förfrÄgan.
Avancerade ViewSet-tekniker
Utöver grundlÀggande anvÀndning och anpassning erbjuder ViewSets avancerade tekniker för att bygga sofistikerade API:er:
Filtrering
DRF tillhandahÄller kraftfulla filtreringsmöjligheter som gör att du kan filtrera queryset baserat pÄ förfrÄgningsparametrar. Du kan anvÀnda attributet filter_backends
för att ange vilka filtrerings-backends som ska anvÀndas. Du kan till exempel anvÀnda SearchFilter
för att lÄta anvÀndare söka efter produkter baserat pÄ namn eller beskrivning:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework import filters
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['name', 'description']
I det hÀr exemplet anger attributet filter_backends
att SearchFilter
ska anvÀndas. Attributet search_fields
anger de fÀlt som ska sökas i.
Pagenering
DRF tillhandahÄller pageneringsmöjligheter som gör att du kan dela upp queryset i mindre sidor. Detta Àr anvÀndbart vid hantering av stora datamÀngder. Du kan anvÀnda attributet pagination_class
för att ange vilken pagenerings-klass som ska anvÀndas. Du kan till exempel anvÀnda PageNumberPagination
för att pagenera resultat med sidnummer:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.pagination import PageNumberPagination
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = PageNumberPagination
I det hÀr exemplet anger attributet pagination_class
att PageNumberPagination
ska anvÀndas. Du kan ocksÄ anpassa pageneringsbeteendet genom att skapa en egen pagenerings-klass.
Autentisering och behörigheter
DRF tillhandahÄller flexibla autentiserings- och behörighetsmekanismer som gör att du kan kontrollera Ätkomsten till dina API-slutpunkter. Du kan anvÀnda attributen authentication_classes
och permission_classes
för att ange vilka autentiserings- och behörighetsklasser som ska anvÀndas. Du kan till exempel anvÀnda TokenAuthentication
för att autentisera anvÀndare med hjÀlp av tokens och behörigheten IsAuthenticated
för att endast tillÄta autentiserade anvÀndare att komma Ät API:et:
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
I det hÀr exemplet anger attributet authentication_classes
att TokenAuthentication
ska anvÀndas, och attributet permission_classes
anger att behörigheten IsAuthenticated
ska anvÀndas.
BÀsta praxis för anvÀndning av ViewSets
För att sÀkerstÀlla att dina ViewSets Àr vÀldesignade och underhÄllbara, följ dessa bÀsta praxis:
- HÄll ViewSets fokuserade: Varje ViewSet bör ansvara för att hantera en enda resurs eller en nÀra relaterad uppsÀttning resurser. Undvik att skapa alltför komplexa ViewSets som hanterar flera orelaterade operationer.
- AnvÀnd lÀmpliga ViewSet-typer: VÀlj den ViewSet-typ som bÀst passar ditt API:s krav. AnvÀnd
ReadOnlyModelViewSet
för skrivskyddade API:er,ModelViewSet
för CRUD-API:er ochGenericViewSet
ellerViewSet
för anpassade API:er. - Följ RESTful-principer: Designa dina API-slutpunkter enligt RESTful-principer. AnvÀnd standardmÀssiga HTTP-metoder (GET, POST, PUT, PATCH, DELETE) för att utföra operationer pÄ resurser.
- AnvÀnd serializers för datavalidering: AnvÀnd serializers för att validera den data som skickas till och tas emot frÄn API:et. Detta hjÀlper till att sÀkerstÀlla dataintegritet och förhindra fel.
- Implementera korrekt autentisering och behörigheter: SÀkra dina API-slutpunkter genom att implementera korrekt autentisering och behörigheter. Detta hjÀlper till att skydda din data frÄn obehörig Ätkomst.
- Skriv omfattande tester: Skriv omfattande tester för att sÀkerstÀlla att dina ViewSets fungerar korrekt. Detta hjÀlper till att förhindra regressioner och gör det lÀttare att underhÄlla koden.
Internationalisering (i18n) och lokalisering (l10n) övervÀganden
NÀr du bygger API:er för en global publik Àr det viktigt att tÀnka pÄ internationalisering (i18n) och lokalisering (l10n). ViewSets kan anpassas för att stödja flera sprÄk och regioner:
- Serializer-fÀlt: AnvÀnd DRF:s serializer-fÀlt med lÀmpliga översÀttningsfunktioner (t.ex.
gettext
frÄn Djangos i18n-ramverk) för att visa översatta fÀltetiketter och hjÀlptexter. - Felmeddelanden: Se till att felmeddelanden som returneras av API:et översÀtts till anvÀndarens föredragna sprÄk.
- Datum- och tidsformatering: AnvÀnd lÀmplig datum- och tidsformatering baserat pÄ anvÀndarens lokala instÀllningar. DRF erbjuder alternativ för att anpassa datum- och tidsformat.
- Valutformatering: Formatera valutavĂ€rden enligt anvĂ€ndarens lokala instĂ€llningar. ĂvervĂ€g att anvĂ€nda bibliotek som
babel
för valutformatering. Till exempel kan ett pris pÄ 1234.56 USD formateras som $1,234.56 i USA, men som 1.234,56 $ i vissa europeiska lÀnder. - Tidszoner: Hantera tidszoner korrekt. Lagra datum och tider i UTC och konvertera dem till anvÀndarens lokala tidszon nÀr de visas.
Till exempel kan en produkt ha en beskrivning som behöver översÀttas. Du skulle anvÀnda Djangos översÀttningssystem inom serializeren:
# serializers.py
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
description = serializers.CharField(help_text=_("Product description"))
class Meta:
model = Product
fields = '__all__'
Och i dina mallar eller kod som anvÀnder denna serializer, se till att rÀtt sprÄk Àr aktiverat.
Exempel: E-handels-API med internationellt stöd
FörestÀll dig ett e-handels-API som sÀljer produkter globalt. Product
-modellen kan inkludera fÀlt som name
, description
, price
och image
. API:et mÄste stödja flera sprÄk och valutor.
ViewSet skulle hantera de grundlÀggande CRUD-operationerna för produkter. Serializers skulle anpassas för att stödja översÀttning av produktnamn och beskrivning. API:et skulle ocksÄ inkludera slutpunkter för att hÀmta produkter per kategori, filtrera produkter efter prisintervall och söka efter produkter efter nyckelord. Dessa funktioner skulle behöva ta hÀnsyn till internationalisering, sÀrskilt kring söktermer och produktbeskrivningar som kan skilja sig mellan sprÄk.
Exempel pÄ URL:er:
/en/products/
- Lista över produkter pÄ engelska/fr/products/
- Lista över produkter pÄ franska/en/products/?currency=USD
- Lista över produkter i USD/fr/products/123/?currency=EUR
- Detaljer om produkt 123 pÄ franska, pris visas i EUR
Slutsats
Django REST Framework ViewSets erbjuder ett kraftfullt och elegant sÀtt att organisera dina API-slutpunkter. Genom att kapsla in relaterade vyer i en enda klass frÀmjar ViewSets kodÄteranvÀndning, förenklar routing och förbÀttrar kodens lÀsbarhet. Med möjligheten att anpassa ViewSets genom att ÄsidosÀtta metoder, lÀgga till anpassade ÄtgÀrder och anvÀnda anpassade serializers, kan du skrÀddarsy dem för att uppfylla ditt API:s specifika krav. Genom att följa de bÀsta praxis som beskrivs i denna guide kan du sÀkerstÀlla att dina ViewSets Àr vÀldesignade, underhÄllbara och skalbara, vilket resulterar i robusta och effektiva API:er.
Kom ihÄg att tÀnka pÄ internationalisering och lokalisering nÀr du bygger API:er för en global publik. Anpassa dina ViewSets och serializers för att stödja flera sprÄk, valutor och tidszoner för att ge en sömlös upplevelse för anvÀndare över hela vÀrlden.
Genom att bemÀstra ViewSets kan du ta dina Django REST Framework-kunskaper till nÀsta nivÄ och bygga API:er som Àr bÄde kraftfulla och underhÄllbara. Detta bidrar till högkvalitativ programvara och en positiv anvÀndarupplevelse för din globala publik.
Denna guide bör fungera som en solid grund för att förstÄ och implementera ViewSets i dina Django REST Framework-projekt. FortsÀtt att öva, experimentera och utforska DRF-dokumentationen för att bli en sann ViewSet-mÀstare!